package sf.dynamicsql.dao;

import org.mybatis.dynamic.sql.delete.DeleteModel;
import org.mybatis.dynamic.sql.delete.render.DeleteStatementProvider;
import org.mybatis.dynamic.sql.insert.GeneralInsertModel;
import org.mybatis.dynamic.sql.insert.InsertSelectModel;
import org.mybatis.dynamic.sql.insert.render.BatchInsert;
import org.mybatis.dynamic.sql.insert.render.GeneralInsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertSelectStatementProvider;
import org.mybatis.dynamic.sql.insert.render.InsertStatementProvider;
import org.mybatis.dynamic.sql.insert.render.MultiRowInsertStatementProvider;
import org.mybatis.dynamic.sql.select.SelectModel;
import org.mybatis.dynamic.sql.select.render.SelectStatementProvider;
import org.mybatis.dynamic.sql.update.UpdateModel;
import org.mybatis.dynamic.sql.update.render.UpdateStatementProvider;
import sf.common.wrapper.Page;
import sf.database.dao.DBClient;
import sf.database.jdbc.sql.Crud;
import sf.spring.util.Assert;

import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.stream.Stream;

public class DBDynmicSQLImpl implements DBDynmicSQL {
    protected DBClient client;

    public DBDynmicSQLImpl(DBClient client) {
        this.client = client;
    }

    @Override
    public <T> int[] insertBatch(BatchInsert<T> provider, List<T> records, boolean insertFast, int batchSize, List<String> pkeys, List<Map<String, Object>> keyValues) {
        Assert.notNull(records, "不能为空");
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().insertBatch(conn, provider, records, insertFast, batchSize, pkeys, keyValues)));
    }

    @Override
    public <T> int[] insertBatch(boolean insertFast, int batchSize, List<String> pkeys, List<Map<String, Object>> keyValues, MultiRowInsertStatementProvider<T> provider) {
        Assert.notNull(provider, "不能为空");
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().insertBatch(conn, insertFast, batchSize, pkeys, keyValues, provider)));
    }

    @Override
    public <T> int insert(List<String> pkeys, Map<String, Object> keyValues, InsertStatementProvider<T> provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().insert(conn, pkeys, keyValues, provider)));
    }

    @Override
    public int insert(List<String> pkeys, Map<String, Object> keyValues, GeneralInsertStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().insert(conn, pkeys, keyValues, provider)));
    }

    @Override
    public int insertSelect(List<String> pkeys, Map<String, Object> keyValues, InsertSelectStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().insertSelect(conn, pkeys, keyValues, provider)));
    }

    @Override
    public int update(UpdateStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().update(conn, provider)));
    }

    @Override
    public int delete(DeleteStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().delete(conn, provider)));
    }

    @Override
    public <T> Page<T> selectPage(long start, int limit, Class<T> beanClass, SelectStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().selectPage(conn, start, limit, beanClass, provider)));
    }

    @Override
    public <T> Page<T> selectPageRaw(long start, int limit, Class<T> beanClass, SelectStatementProvider countProvider, SelectStatementProvider listProvider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().selectPageRaw(conn, start, limit, beanClass, countProvider, listProvider)));
    }

    @Override
    public Object[] selectArray(SelectStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().selectArray(conn, provider)));
    }

    @Override
    public <T> List<T> selectList(Class<T> beanClass, SelectStatementProvider provider) {
        Assert.notNull(beanClass, "返回类型不能为空");
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().selectList(conn, beanClass, provider)));
    }

    @Override
    public <T> List<T> selectList(Class<T> beanClass, SelectStatementProvider provider, long start, int limit) {
        Assert.notNull(beanClass, "返回类型不能为空");
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().selectList(conn, beanClass, provider, start, limit)));
    }

    @Override
    public <T> T selectOne(Class<T> beanClass, SelectStatementProvider provider) {
        Assert.notNull(beanClass, "返回类型不能为空");
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().selectOne(conn, beanClass, provider)));
    }

    @Override
    public List<Map<String, Object>> select(SelectStatementProvider provider) {
        return client.executeFunc((conn -> Crud.getInstance().getDynmicSQLInf().select(conn, provider)));
    }

    @Override
    public <T> void selectIterator(Consumer<Iterable<T>> ormIt, Class<T> returnClass, SelectStatementProvider provider) {
        Assert.notNull(returnClass, "返回类型不能为空");
        client.executeFunc((conn -> {
            Crud.getInstance().getDynmicSQLInf().selectIterator(conn, ormIt, returnClass, provider);
            return null;
        }));
    }

    @Override
    public <T> void selectStream(Consumer<Stream<T>> ormStream, Class<T> returnClass, SelectStatementProvider provider) {
        Assert.notNull(returnClass, "返回类型不能为空");
        client.executeFunc((conn -> {
            Crud.getInstance().getDynmicSQLInf().selectStream(conn, ormStream, returnClass, provider);
            return null;
        }));
    }

    @Override
    public int insert(List<String> pkeys, Map<String, Object> keyValues, GeneralInsertModel generalInsertModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().insert(conn, pkeys, keyValues, generalInsertModel));
    }

    @Override
    public int insertSelect(List<String> pkeys, Map<String, Object> keyValues, InsertSelectModel insertSelectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().insertSelect(conn, pkeys, keyValues, insertSelectModel));
    }

    @Override
    public int update(UpdateModel updateModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().update(conn, updateModel));
    }

    @Override
    public int delete(DeleteModel deleteModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().delete(conn, deleteModel));
    }

    @Override
    public <T> Page<T> selectPage(long start, int limit, Class<T> beanClass, SelectModel selectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().selectPage(conn, start, limit, beanClass, selectModel));
    }

    @Override
    public <T> Page<T> selectPageRaw(long start, int limit, Class<T> beanClass, SelectModel countSelectModel, SelectModel listSelectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().selectPageRaw(conn, start, limit, beanClass, countSelectModel, listSelectModel));
    }

    @Override
    public Object[] selectArray(SelectModel selectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().selectArray(conn, selectModel));
    }

    @Override
    public <T> List<T> selectList(Class<T> beanClass, SelectModel selectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().selectList(conn, beanClass, selectModel));
    }

    @Override
    public <T> List<T> selectList(Class<T> beanClass, SelectModel selectModel, long start, int limit) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().selectList(conn, beanClass, selectModel));
    }

    @Override
    public <T> T selectOne(Class<T> beanClass, SelectModel selectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().selectOne(conn, beanClass, selectModel));
    }

    @Override
    public List<Map<String, Object>> select(SelectModel selectModel) {
        return client.executeFunc(conn -> Crud.getInstance().getDynmicSQLModelInf().select(conn, selectModel));
    }

    @Override
    public <T> void selectIterator(Consumer<Iterable<T>> ormIt, Class<T> returnClass, SelectModel selectModel) {
        client.executeFunc(conn -> {
            Crud.getInstance().getDynmicSQLModelInf().selectIterator(conn, ormIt, returnClass, selectModel);
            return null;
        });
    }

    @Override
    public <T> void selectStream(Consumer<Stream<T>> ormStream, Class<T> returnClass, SelectModel selectModel) {
        client.executeFunc(conn -> {
            Crud.getInstance().getDynmicSQLModelInf().selectStream(conn, ormStream, returnClass, selectModel);
            return null;
        });
    }
}
